package top.goldenyear.porpoise.framework.web.core.generator;

import cn.hutool.v7.core.collection.CollUtil;
import com.jfinal.kit.Kv;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import top.goldenyear.porpoise.framework.web.core.generator.config.GlobalConfig;
import top.goldenyear.porpoise.framework.web.core.generator.config.ModuleConfig;
import top.goldenyear.porpoise.framework.web.core.generator.config.TableConfig;
import top.goldenyear.porpoise.framework.web.core.generator.model.TableMeta;

/**
 * 代码生成器
 *
 * @author airhead
 */
@Setter
@Getter
@Slf4j
public abstract class BaseGenerator {
  protected final GlobalConfig globalConfig;
  protected IMetaBuilder metaBuilder;
  protected CodeEngine codeEngine;

  public BaseGenerator() {
    this.globalConfig = new GlobalConfig();
    this.codeEngine = new CodeEngine();

    initConfig();
  }

  public void generateFile() {
    List<Kv> list = generateCode();
    for (Kv kv : list) {
      codeEngine.generateFile(kv);
    }
  }

  public void generateFile(List<Kv> codeList) {
    if (CollUtil.isEmpty(codeList)) {
      return;
    }

    for (Kv kv : codeList) {
      codeEngine.generateFile(kv);
    }
  }

  /**
   * execute 只是生成数据
   *
   * @return
   */
  public List<Kv> generateCode() {
    initMetaBuilder();

    if (metaBuilder == null) {
      throw new RuntimeException("metaBuilder 为空，请先设置 metaBuilder");
    }

    List<Kv> codeList = new ArrayList<>();
    try {
      List<TableMeta> tableMetas = metaBuilder.buildTables();
      Map<String, Boolean> generateConfigs = globalConfig.getGenerateConfigs();
      Boolean overwrite = globalConfig.getOverwrite();
      tableMetas.forEach(
          tableMeta -> {
            Map<String, ModuleConfig> moduleConfigs = globalConfig.getModuleConfigs();
            moduleConfigs.forEach(
                (module, moduleConfig) -> {
                  Boolean generate = generateConfigs.get(module);
                  // 明确指定不生成, 直接返回
                  if (Boolean.FALSE.equals(generate)) {
                    return;
                  }

                  // 多判断一次是否有单独指定
                  TableConfig tableConfig =
                      globalConfig.getStrategyConfig().getTableConfig(tableMeta.getName());
                  if (tableConfig != null) {
                    generate = tableConfig.getGenerateConfigs().get(module);
                    // 明确指定不生成, 直接返回
                    if (Boolean.FALSE.equals(generate)) {
                      return;
                    }
                  }

                  moduleConfig.setEnableOverwrite(overwrite);

                  codeEngine.setGlobalConfig(globalConfig);
                  codeEngine.setModuleConfig(moduleConfig);
                  Kv bindingData = codeEngine.buildBindingData(tableMeta);
                  Kv kv = codeEngine.generateCode(bindingData);
                  codeList.add(kv);
                });
          });

      log.info("code is generated successfully.");
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }

    return codeList;
  }

  /** 初始化配置 */
  protected abstract void initConfig();

  /** 初始化 MetaBuilder */
  protected abstract void initMetaBuilder();
}
